缓存雪崩、击穿、穿透
马士兵金三银四 - Redis 面试题
- 大量数据同时过期
- 均匀设置过期时间
对缓存数据设置过期时间时,给过期时间加上随机数,保证数据不会在同一时间过期 - 互斥锁
当业务线程处理用户请求时,如果发现用户访问的数据不再 Redis 中,就加个互斥锁,保证同一时间只有一个请求构建缓存,缓存构建完成后再释放锁,未能获取互斥锁的请求等待锁释放后重新读取缓存,或者返回 空/默认值
实现互斥锁时最好设置超时时间,防止请求异常阻塞锁无法释放,导致系统无响应 - 双 key 策略
对缓存数据使用两个 key,主 key 设置过期时间,备 key 不设置过期时间,相当于数据副本
当业务线程访问不到主 key 的缓存数据时,直接返回备 key 的数据,更新数据时主备 key 同时更新
优点:可以快速相应请求,不会因为 key 失效导致大量请求被锁阻塞住(互斥锁),后续再通知后台线程重新构建主 key 数据 - 后台更新缓存
缓存不设置有效期,业务线程不再负责更新缓存,将更新缓存的工作交给后台线程定时更新
但是当系统内存紧张时,有些缓存数据会被淘汰,此时业务线程读取缓存失败,在业务的视角里就是缓存丢失了
解决方案 - 后台线程不仅负责定时更新缓存,同时负责检查缓存是否有效,失效时马上重新载入缓存
- 业务线程发现缓存数据失效后(被淘汰),通过消息队列发送一条消息通知后台线程更新缓存,后台线程接收到消息后判断缓存是否存在,存在则不更新,不存在则重新获取缓存。
相比于第一种方案,缓存更新较及时,用户体验较好
- Redis 故障宕机
- 服务熔断或请求限流
故障宕机导致缓存雪崩时,启动服务熔断机制,暂停业务应用对缓存服务的访问,直接返回错误,不再访问数据库,从而降低对数据库的访问压力,保证数据库的正常运行,等 Redis 恢复后再允许业务访问
服务熔断机制保护了数据库,但是暂停了业务对缓存系统的访问,会导致业务无法正常工作
为了减少对业务的影响可以使用 请求限流 机制,只发送少量请求到数据库进行处理,再多的请求则在入口处拒绝服务,等 Redis 恢复正常并预热缓存后,再解除请求限流 - 构建 Redis 高可用集群
使用主从节点构建 Redis 集群,避免故障宕机导致的缓存雪崩
- 互斥锁
- 不给热点数据设置过期时间,由后台异步更新缓存
- 限制非法请求
- 缓存 空/默认值
- 布隆过滤器